package com.spn.blog.common.utils;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.util.*;
import java.util.concurrent.TimeUnit;


public class RedisCacheUtil implements ApplicationContextAware {

	@Autowired
	RedisTemplate redisTemplate;

	private static ApplicationContext applicationContext = null;

	/**
	 * 缓存基本的对象，Integer、String、实体类等
	 *
	 * @param key   缓存的键值
	 * @param value 缓存的值
	 * @return 缓存的对象
	 */
	public <T> ValueOperations<String, T> setCacheObject(String key, T value) {
		ValueOperations<String, T> operation = redisTemplate.opsForValue();
		operation.set(key, value);
		return operation;
	}



	/**
	 * 缓存基本的对象，Integer、String、实体类等
	 *
	 * @param key      缓存的键值
	 * @param value    缓存的值
	 * @param timeout  时间
	 * @param timeUnit 时间颗粒度
	 * @return 缓存的对象
	 */
	public <T> ValueOperations<String, T> setCacheObject(String key, T value, Integer timeout, TimeUnit timeUnit) {
		ValueOperations<String, T> operation = redisTemplate.opsForValue();
		operation.set(key, value, timeout, timeUnit);
		return operation;
	}

	/**
	 * 获得缓存的基本对象。
	 *
	 * @param key 缓存键值
	 * @return 缓存键值对应的数据
	 */
	public <T> T getCacheObject(String key) {
		ValueOperations<String, T> operation = redisTemplate.opsForValue();
		return operation.get(key);
	}
	

	/**
	 * 删除单个对象
	 *
	 * @param key
	 */
	public void deleteObject(String key) {
		if(this.hashKeys(key)) {
			redisTemplate.delete(key);
		}
	}

	/**
	 * 删除集合对象
	 *
	 * @param collection
	 */
	public void deleteObject(Collection collection) {
		redisTemplate.delete(collection);
	}

	/**
	 * 缓存List数据
	 *
	 * @param key      缓存的键值
	 * @param dataList 待缓存的List数据
	 * @return 缓存的对象
	 */
	public <T> ListOperations<String, T> setCacheList(String key, List<T> dataList) {
		ListOperations listOperation = redisTemplate.opsForList();
		if (null != dataList) {
			int size = dataList.size();
			for (int i = 0; i < size; i++) {
				listOperation.leftPush(key, dataList.get(i));
			}
		}
		return listOperation;
	}

	/**
	 * 获得缓存的list对象
	 *
	 * @param key 缓存的键值
	 * @return 缓存键值对应的数据
	 */
	public <T> List<T> getCacheList(String key) {
		List<T> dataList = new ArrayList<T>();
		ListOperations<String, T> listOperation = redisTemplate.opsForList();
		Long size = listOperation.size(key);

		for (int i = 0; i < size; i++) {
			dataList.add(listOperation.index(key, i));
		}
		return dataList;
	}

	/**
	 * 缓存Set
	 *
	 * @param key     缓存键值
	 * @param dataSet 缓存的数据
	 * @return 缓存数据的对象
	 */
	public <T> BoundSetOperations<String, T> setCacheSet(String key, Set<T> dataSet) {
		BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
		Iterator<T> it = dataSet.iterator();
		while (it.hasNext()) {
			setOperation.add(it.next());
		}
		return setOperation;
	}

	/**
	 * 获得缓存的set
	 *
	 * @param key
	 * @return
	 */
	public <T> Set<T> getCacheSet(String key) {
		Set<T> dataSet = new HashSet<T>();
		BoundSetOperations<String, T> operation = redisTemplate.boundSetOps(key);
		dataSet = operation.members();
		return dataSet;
	}

	/**
	 * 缓存Map
	 *
	 * @param key
	 * @param dataMap
	 * @return
	 */
	public <T> HashOperations<String, String, T> setCacheMap(String key, Map<String, T> dataMap) {
		HashOperations hashOperations = redisTemplate.opsForHash();
		if (null != dataMap) {
			for (Map.Entry<String, T> entry : dataMap.entrySet()) {
				hashOperations.put(key, entry.getKey(), entry.getValue());
			}
		}
		return hashOperations;
	}
	/**
	 * 获得缓存的基本对象。
	 *
	 * @param key 缓存键值
	 * @return 缓存键值对应的数据
	 */
	public int getCacheInt(String key) {
		ValueOperations<String, Integer> operation = redisTemplate.opsForValue();
		return operation.get(key)==null?0:operation.get(key);
	}
	/**
	 * 获得缓存的Map
	 *
	 * @param key
	 * @return
	 */
	public <T> Map<String, T> getCacheMap(String key) {
		Map<String, T> map = redisTemplate.opsForHash().entries(key);
		return map;
	}

	/**
	 * 获得缓存的基本对象列表
	 * 
	 * @param pattern 字符串前缀
	 * @return 对象列表
	 */
	public Collection<String> keys(String pattern) {
		return redisTemplate.keys(pattern);
	}
	/**
	 * 缓存对象数据，指定时间
	 * @param <T>
	 * @param key 缓存的键值
	 * @param value 缓存的值
	 * @param minutes 分钟
	 * @return
	 */
	public <T> ValueOperations<String, T> setCacheData(String key, T value,long minutes) {
		ValueOperations<String, T> operation = redisTemplate.opsForValue();
		operation.set(key, value,Duration.ofMinutes(minutes));
		return operation;
	}
	/**
	 * 缓存对象数据，指定时间
	 * @param <T>
	 * @param key 缓存的键值
	 * @param value 缓存的值
	 * @param minutes 分钟
	 * @return
	 */
	public <T> ValueOperations<String, T> resetCacheData(String key, T value,long minutes) {
		if(this.hashKeys(key)) {
			this.deleteObject(key);
		}
		ValueOperations<String, T> operation = redisTemplate.opsForValue();
		operation.set(key, value,Duration.ofMinutes(minutes));
		return operation;
	}
	/**
	 * 缓存对象数据，指定时间
	 * @param <T>
	 * @param key 缓存的键值
	 * @param value 缓存的值
	 * @param minutes 分钟
	 * @return
	 */
	public <T> ValueOperations<String, T> resetCacheData(String key, T value) {
		if(this.hashKeys(key)) {
			this.deleteObject(key);
		}
		ValueOperations<String, T> operation = redisTemplate.opsForValue();
		operation.set(key, value);
		return operation;
	}
	/**
	 * 判断key是否存在
	 * @param key
	 * @return
	 */
	public boolean hashKeys(String key) {
		return redisTemplate.hasKey(key);
	}
	/**
	 * 模糊删除，*keys
	 * @param key
	 */
	public void deleteBySuffix(String key) {
		Set<String> keys=redisTemplate.keys("*"+key);
        redisTemplate.delete(keys);
	}
	/**
	 * <pre>模糊删除，keys*</pre>
	 * @param key
	 */
	public void deleteByPrex(String key) {
        Set<String> keys = redisTemplate.keys(key + "*");
        redisTemplate.delete(keys);
    }
//	/**
//     *  获取指定前缀的一系列key
//     *  使用scan命令代替keys, Redis是单线程处理，keys命令在KEY数量较多时，
//     *  操作效率极低【时间复杂度为O(N)】，该命令一旦执行会严重阻塞线上其它命令的正常请求
//     * @param keyPrefix
//     * @return
//     */
//    public Set<String> keysPrex(String keyPrefix) {
//        String realKey = "*" + keyPrefix + "*";
//        try {
//            return (Set<String>) redisTemplate.execute((RedisCallback<Set<String>>) connection -> {
//                Set<String> binaryKeys = new HashSet<>();
//                Cursor<byte[]> cursor = connection.scan(new ScanOptions.ScanOptionsBuilder().match(realKey).count(Integer.MAX_VALUE).build());
//                while (cursor.hasNext()) {
//                    binaryKeys.add(new String(cursor.next()));
//                }
//                return binaryKeys;
//            });
//        } catch (Throwable e) {
//            e.printStackTrace();
//        }
//        return null;
//    }

//    /**
//     *  删除指定前缀的一系列key
//     * @param keyPrefix
//     */
//    public boolean removeAll(String keyPrefix) {
//        try {
//            Set<String> keys = keysPrex(keyPrefix);
//            if(keys!=null) {
//                redisTemplate.delete(keys);
//               }
//            return true;
//        } catch (Throwable e) {
//            e.printStackTrace();
//            return false;
//        }
//    }
    
    public long getExpire(String key,TimeUnit timeUnit) {
    	return redisTemplate.getExpire(key, timeUnit);
    }
    public long getExpireMin(String key) {
    	return redisTemplate.getExpire(key, TimeUnit.MINUTES);
    }
    
    public long getExpireSeconds(String key) {
    	return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		if (RedisCacheUtil.applicationContext == null) {
			RedisCacheUtil.applicationContext = applicationContext;
		}
	}

	//通过name获取 Bean
	public static Object getBean(String name) {
		return getApplicationContext().getBean(name);
	}
	//获取applicationContext
	public static ApplicationContext getApplicationContext() {
		return applicationContext;
	}

//    /**
//	 * 缓存List数据
//	 *
//	 * @param key      缓存的键值
//	 * @param list 待缓存的List数据
//	 * @return
//	 * @return 缓存的对象
//	 */
//	public <T> Object setListString(String key, List<T> list) {
//		if(this.hashKeys(key)) {this.deleteObject(key);}
//
//		ValueOperations<String, Object> operation = redisTemplate.opsForValue();
//		operation.set(key, Jacksons.toJSONString(list));
//		return operation;
//	}
//	/**
//	 * 获得缓存的list对象
//	 *
//	 * @param key 缓存的键值
//	 * @return 缓存键值对应的数据
//	 */
//	public <T> List<T> getListString(String key,Class<T> clazz) {
//		if(!this.hashKeys(key)) {return null;}
//		ValueOperations<String, Object> operation = redisTemplate.opsForValue();
//		Object rsdata = operation.get(key);
//		List<T> list = Jacksons.toList(rsdata.toString(), clazz);//JSONObject.parseArray(rsdata.toString(),clazz);
//		return list;
//	}
}
